home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Floppyshop 2
/
Floppyshop - 2.zip
/
Floppyshop - 2.iso
/
diskmags
/
5791-.end
/
dmg-6260
/
articles
/
sai.doc
< prev
next >
Wrap
Text File
|
1993-07-23
|
10KB
|
216 lines
SIMULATED ARTIFICIAL INTELLIGENCE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Have you ever played one of those strategy games and wondered how the
programmers managed to make the enemy decide what to do next, instead
of just running up and attacking you? Believe me, so have I. So I
decided to create my own method of what I call 'Simulated Artificial
Intelligence' (SAI).
My routine contains a list of 'Resultant Variables' (RV's), which is
simply a list of variable names - one for each possible action. I
decided to base my SAI on a typical overhead scene with several
'intelligent' characters battling it out with eachother. Eventually, it
works quite well (well...sort of...ish)
Here's how it works:
Let's say that any given character can perform one of these actions:
ATTACK, ADVANCE, RETREAT, CAST FIREBALL, SHOOT ARROW, or PAUSE.
For simplicity's sake, we will call the variable names:
ATT, ADV, RET, CFR, SHA, PAU.
At the beginning of each 'loop', we set each of these RV's to 0%
ATT=0 : ADV=0 : RET=0 : CFR=0 : SHA=0 : PAU=0
Now, when it comes to the computer's turn, a collection of other
statistics increase or decrease the chance of each action being
performed. Let's introduce these statistics:
HEALTH (decreases when hit or attacked, dead if 0)
BRAVERY (measure of cowardice or bravery)
CAST SKILL (how accurate you are at hitting with a fireball)
BOW SKILL (how accurate you are at hitting with an arrow)
WEAPON SKILL (how good a fighter you are)
NUMBER OF FIREBALLS (how many fireballs you have left)
NUMBER OF ARROWS (how many arrows you have left)
WASTEAGE (how much you preserve or waste your fireballs/arrows)
Let's take each RV in turn:
PROBABILITY OF ATTACKING AN ADJACENT ENEMY (ATT)
How healthy you are determines this up to some extent. If you had a
health value of 80% or above, the probability of attacking would
increase. If health was between 40% and 80%, the attack prob would not
increase by much, and if health was below 40%, the attack prob would
decrease.
If you are very brave, you will leap straight into battle, thus setting
the attack RV to 90% and over (before modifications of health, etc.) If
you are a coward, the attack prob would drastically lessen.
Weapon skill would also make a change. If you were confident with your
weapon, you would attack with no doubt, whereas if you are weak in this
area, you would be less likely to attack.
After these three modifications, you will get a number in ATT. Here are
five examples of character's ATT RV's:
Health 100% Health 80% Health 60% Health 40% Health 20%
Bravery 100% Bravery 85% Bravery 75% Bravery 60% Bravery 45%
W/skill 100% W/skill 85% W/skill 70% W/skill 55% W/skill 35%
~~~~~~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~~~~
ATT:100%+ ATT:80%-100% ATT:65%-75% ATT:40%-65% ATT:0%-25%
Next comes PROBABILITY OF ADVANCING TOWARDS CHOSEN TARGET.
Health plays another part here, but on a slightly less scale. Bravery
would play a slightly bigger part. The main thing would be the current
action of the target. If the target was storming towards you, you would
be less likely to advance than if he was running away, screaming.
The PROBABILITY OF RETREATING can be said to be inversely proportional
to the probability of advancing, but to make the routine complete, we
calculate the probability separately like the others. Here, we would
include health, bravery, target's current action, etc.
The PROBABILITY OF CASTING A FIREBALL uses different variables. If you
were to find yourself confronting an enemy, one of the first things you
would do is loose off a few fireballs or arrows to soften him up a bit.
We take into consideration how many fireballs we have left; if we had
twenty, we would cast loads of them, but if we only had one or two, we
would save them for later. To modify this, we introduce a stat called
'wasteage'. This determines whether we waste our long-range resources,
or conserve them. The higher the wasteage percentage, the more likely
the character is to shoot a fireball. Finally, the character's
spellcasting ability is taken into consideration. If he knows he is a
bad spellcaster, then he is less likely to cast one, than if he was a
master. On top of these three, I have also added two more modifiers:
Health state; (if you were weak, you would want your opponent as far
away from you as possible), and Target's current action (ie. keeping
him away if he was advancing, or shooting him in the back if he was
retreating.)
The PROBABILITY OF SHOOTING AN ARROW uses virtually the same methods as
the fireball-casting one above, with these exceptions. The average
person carries more arrows than fireballs, and so has more to shoot. It
is easier for the average person to shoot an arrow rather than to cast
a spell. These all increase the chance of an arrow being shot rather
than a fireball.
Finally, THE PROBABILITY OF PAUSING is a 'dividing line' between
advancing and retreating. It is typically an 'unsure' or 'second
thoughts' option, and can be basically an average of the attack prob
and retreat prob.
OK, finally we have sorted out the actions. We should now have a list
of resultant variables, each containing a percentage value. We add a
random number to each of these (say between -10% to 10%) for variety.
Random numbers are also used often in the main equations, but should
not bias the results too greatly. We should also note that the contents
of the RV's should not be taken as 'gospel'. Even if you were a tough
and brave fighter, you might have a sudden urge to shoot an arrow, or
shift position a bit, and so a 'low-probability alteration' routine is
added near the end. We simply set up some tables which have a direct
link to the current action, and say that there is a probability of
maybe 1 in 40 that the character will suddenly change action;
discerning the change in the environment (eg. having two more enemies
lumbering up to you, or your current target running off.)
Here are some examples of these tables:
ACTION: Attack Retreat Shoot arrow
LINKED ACTIONS: Advance Cast fireball Cast fireball
Cast fireball Shoot arrow Advance
Shoot arrow Pause Retreat
*NOT* A LINKED ACTION: Retreat Advance ?
So, for example, someone who is retreating may suddenly decide to cast
a fireball, or pause to think 'why am, I running?'
At the end of all of these modifications, we must now decide which
action is to be taken. The simple way of doing this is to see which of
the RV's has the biggest number, or biggest percentage chance of being
carried out. To do this, we take two empty variables, MAXVALUE and
VALUE (NB: syntax: max VALUE !)
MAXVALUE is set to 0, and so is VALUE. MAXVALUE refers to the biggest
probability we have encountered so far, and VALUE refers to the actual
action which has has the biggest percentage so far.
We go through each action, and compare it's value with MAXVALUE. If it
is lower, then it is discarded, if it is higher, MAXVALUE is set to
that value, and VALUE is set to the action number. This routine is
repeated until all of the actions have been covered. It is up to you
what equal values determine, (eg. MAXVALUE=80%, NEXT VALUE=80%) whether
they are discarded or used.
Now we have determined the current action in the hero's mind, all we
have to do now is write the code to carry out the action! On this disk
is a program called INTEL.BAS and contains most of the stuff written in
this article. There is a value in line 2 which holds how many
characters there are. This can range from 2 to 10.
Just to clear up a couple of loose ends, here is how a character
determines who to advance toward/shoot at, etc.:
The method used in my example program is to simply see who is the
closest, and then act upon it. So, if the closest enemy was very big
and strong, you would run off (ideally), and if weak, attack. To
calculate the closest enemy, run through each character in turn, using
Pythagoras' Theorem. For those of you who chose to sleep through GCSE
maths, here it is:
"Pythagoras' Theorem states that the square of the hypotenuse (longest
side) of a right-angled triangle is equal to the square of the other
two sides."
This can be used to convert an X- and Y-axis difference into one
length. So,
HERO POSITION = 2,5
TARGET POSITION = 9,3
X DIFFERENCE = max(hpx,tpx)-min(hpx,tpx) [rids any negative numbers,
you can also use ABS.]
Y DIFFERENCE = max(hpy,tpy)-min(hpy,tpy) [same applies]
XDIFF=7
YDIFF=2
DIFFERENCE = SQUARE ROOT OF ( (XDIFF*XDIFF) + (YDIFF*YDIFF) )
DIFFERENCE = SQR ( (7*7) + (2*2) )
DIFFERENCE = SQR (49+4)
DIFFERENCE = SQR (53)
DIFFERENCE = 7.280109889
DIFFERENCE = 7 SQUARES
Using the same method of finding the heighest probability, we find out
the closest enemy. Although the method is the same, the initial
MAXVALUE has to be 99, not 0, because every target is further than 0
squares away from the character. We also say if VALUE is lower than
MAXVALUE, and not if VALUE is higher than MAXVALUE. To avoid confusion,
use MINVALUE instead.
So, we know who is the target, and we know what action to perform. Once
the action has been performed, the program moves on to the next
character and performs the same operation. Once all characters have had
their 'turn', we start all over again. This continues until everybody
but one is dead!
Check out INTEL.BAS to see this whole thing in motion. and remember,
the routine above is only for an over-head RPG. For chess games or
whatever, I'm afraid it's up to you!
Article: BLACK EAGLE 23/7/93